from django.db import models
from django.conf import settings
from django.core.exceptions import ValidationError
from django.utils import timezone


class Scene(models.Model):
    """智能场景模型"""
    name = models.CharField(max_length=60, verbose_name="场景名称")
    owner = models.ForeignKey(
        settings.AUTH_USER_MODEL,  # 改为使用标准的 User 模型
        on_delete=models.CASCADE,
        related_name='scenes',
        verbose_name="场景拥有者"
    )
    description = models.TextField(blank=True, verbose_name="场景描述")
    priority = models.SmallIntegerField(default=5, verbose_name="优先级")
    enabled = models.BooleanField(default=True, verbose_name="是否启用")
    auto_execute = models.BooleanField(default=True, verbose_name="自动执行")
    created_at = models.DateTimeField(default=timezone.now, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")

    class Meta:
        ordering = ['-priority', 'id']
        verbose_name = "智能场景"
        verbose_name_plural = "智能场景"
        indexes = [
            models.Index(fields=['owner', 'enabled']),
            models.Index(fields=['priority']),
        ]

    def __str__(self):
        return f"{self.name} (优先级={self.priority})"

    def clean(self):
        """模型验证"""
        if self.priority < 1 or self.priority > 100:
            raise ValidationError("优先级必须在1-100之间")

    def save(self, *args, **kwargs):
        self.clean()
        super().save(*args, **kwargs)


class Trigger(models.Model):
    """场景触发器"""
    
    class TriggerType(models.TextChoices):
        TIME = 'time', '定时触发'
        TIME_RANGE = 'time_range', '时间范围'
        DEVICE_STATE = 'device_state', '设备状态'
        WEATHER = 'weather', '天气条件'
        LOCATION = 'location', '位置触发'
        MANUAL = 'manual', '手动触发'
    
    scene = models.ForeignKey(
        Scene,
        on_delete=models.CASCADE,
        related_name='triggers',
        verbose_name="关联场景"
    )
    name = models.CharField(max_length=50, blank=True, verbose_name="触发器名称")
    type = models.CharField(
        max_length=20,
        choices=TriggerType.choices,
        verbose_name="触发器类型"
    )
    config = models.JSONField(verbose_name="触发器配置")
    enabled = models.BooleanField(default=True, verbose_name="是否启用")
    created_at = models.DateTimeField(default=timezone.now, verbose_name="创建时间")

    class Meta:
        verbose_name = "场景触发器"
        verbose_name_plural = "场景触发器"

    def __str__(self):
        display_name = self.name or f"{self.get_type_display()}触发器"
        return f"{display_name} ({self.scene.name})"

    def clean(self):
        """验证触发器配置"""
        if not isinstance(self.config, dict):
            raise ValidationError("触发器配置必须是JSON对象")


class Action(models.Model):
    """场景动作"""
    
    class ActionType(models.TextChoices):
        DEVICE_CONTROL = 'device_control', '设备控制'
        NOTIFICATION = 'notification', '发送通知'
        DELAY = 'delay', '延时等待'
        SCENE_TRIGGER = 'scene_trigger', '触发其他场景'
    
    scene = models.ForeignKey(
        Scene,
        on_delete=models.CASCADE,
        related_name='actions',
        verbose_name="关联场景"
    )
    name = models.CharField(max_length=50, blank=True, verbose_name="动作名称")
    type = models.CharField(
        max_length=20,
        choices=ActionType.choices,
        default=ActionType.DEVICE_CONTROL,
        verbose_name="动作类型"
    )
    device = models.ForeignKey(
        'device_simulation.Device',
        on_delete=models.CASCADE,
        verbose_name="目标设备"
    )
    command = models.JSONField(verbose_name="执行命令")
    order = models.PositiveIntegerField(default=0, verbose_name="执行顺序")
    enabled = models.BooleanField(default=True, verbose_name="是否启用")
    retry_count = models.PositiveIntegerField(default=0, verbose_name="重试次数")
    created_at = models.DateTimeField(default=timezone.now, verbose_name="创建时间")

    class Meta:
        verbose_name = "场景动作"
        verbose_name_plural = "场景动作"
        ordering = ['order', 'id']

    def __str__(self):
        display_name = self.name or f"{self.get_type_display()}动作"
        return f"{display_name} ({self.scene.name})"

    def clean(self):
        """验证动作配置"""
        # 设备控制类型必须指定 device
        if self.type == self.ActionType.DEVICE_CONTROL and not self.device:
            raise ValidationError("设备控制动作必须指定目标设备")
        # 命令必须为 dict
        if not isinstance(self.command, dict):
            raise ValidationError("执行命令必须是JSON对象")

    def save(self, *args, **kwargs):
        # 在保存前执行清理和校验
        self.clean()
        super().save(*args, **kwargs)


class SceneExecutionLog(models.Model):
    """场景执行日志"""
    
    class Invoker(models.TextChoices):
        AUTO = 'auto', '自动触发'
        MANUAL = 'manual', '手动触发'
        SCENE = 'scene', '场景触发'

    class Status(models.TextChoices):
        RUNNING = 'running', '执行中'
        SUCCESS = 'success', '成功'
        ERROR = 'error', '失败'
        SKIPPED = 'skipped', '跳过'
        PARTIAL_SUCCESS = 'partial_success', '部分成功'

    scene = models.ForeignKey(
        Scene,
        on_delete=models.CASCADE,
        related_name='execution_logs',
        verbose_name="关联场景"
    )
    invoker = models.CharField(
        max_length=10,
        choices=Invoker.choices,
        default=Invoker.AUTO,
        verbose_name="触发方式"
    )
    status = models.CharField(
        max_length=20,
        choices=Status.choices,
        default=Status.RUNNING,
        verbose_name="执行状态"
    )
    detail = models.TextField(blank=True, verbose_name="执行详情")
    duration_ms = models.PositiveIntegerField(null=True, blank=True, verbose_name="执行耗时(毫秒)")
    ts = models.DateTimeField(auto_now_add=True, verbose_name="执行时间")

    class Meta:
        verbose_name = "场景执行日志"
        verbose_name_plural = "场景执行日志"
        ordering = ['-ts']
        indexes = [
            models.Index(fields=['scene', '-ts']),
            models.Index(fields=['status', '-ts']),
        ]

    def __str__(self):
        return f"[{self.ts}] {self.scene.name} {self.get_invoker_display()} → {self.get_status_display()}"